﻿using System;
using System.Threading;
using System.Collections.Generic;
using System.Collections.Concurrent;

namespace oueb
{
    using Ceen;
    using Ceen.Httpd;
    using core;

    public class OuebServer : IOuebServer
    {
        internal ConcurrentQueue<CancellationTokenSource> m_token;
        internal ServerConfig config;
        internal OuebUri[] uris;
        public IEnumerable<OuebUri> Uris { get => uris; }
        public bool Runing
        {
            get
            {
                if (m_token.Count != 0 && m_token.TryPeek(out var token)) return !token.IsCancellationRequested;
                return false;
            }
        }
        public OuebServer(params string[] listen_uris)
        {
            config = new ServerConfig();
            m_token = new ConcurrentQueue<CancellationTokenSource>();
            if (listen_uris.Length > 0) this.SetListenUris(listen_uris);
        }

        public IOuebServer UseCors(Action<CorsBuilder> corsBuilderAction)
        {
            var corsBuilder = new CorsBuilder();
            corsBuilderAction.Invoke(corsBuilder);
            config.AddRoute(corsBuilder.Build());
            return this;
        }
        public IOuebServer UseCorsNoLimit()
        {
            return UseCors(o => o.AllowAnyHeaders().AllowAnyMethod().AllowAnyOrigin());
        }
        public void AddRoute(string path, HttpHandlerDelegate deal)
        {
            config.AddRoute(path, deal);
        }
        public IOuebServer AddRoute(string path, IHttpModule deal)
        {
            config.AddRoute(path, deal);
            return this;
        }
        public IOuebServer AddRoute(IHttpModule deal)
        {
            config.AddRoute(deal);
            return this;
        }
        public long MaxPostSize { get {return config.MaxPostSize;} set { config.MaxPostSize = value; } }
        public IOuebServer Listen()
        {
            while (m_token.TryDequeue(out var _token))
                _token.Cancel();

            var token = new CancellationTokenSource();
            m_token.Enqueue(token);
            foreach (var uri in LoopListenUris()) HttpServer.ListenAsync(uri, uri.onssl, config, token.Token);
            return this;
        }

        public IEnumerable<OuebUri> LoopListenUris()
        {
            for (int i = 0; i < uris.Length; i++) yield return uris[i];
        }

        public IOuebServer SetListenUris(params string[] _uris)
        {
            uris = new OuebUri[_uris.Length];
            for (int i = 0; i < uris.Length; i++) uris[i] = new OuebUri(_uris[i]);
            return this;
        }

        public IOuebServer SetServerName(string servername)
        {
            config.DefaultServerName = servername;
            return this;
        }

        public IOuebServer Shutdown()
        {
            while (m_token.TryDequeue(out var _token))
                _token.Cancel();
            return this;
        }
    }
}
